﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web.Mvc;
using RotaractProjectCalendar.DataAccessLayer;
using RotaractProjectCalendar.Models;
using RotaractProjectCalendar.ViewModels;

namespace RotaractProjectCalendar.Areas.Admin.Controllers
{
    [Authorize(Roles = "Admin")]
    public class CoordinatorController : Controller
    {
        private readonly CalendarContext _db = new CalendarContext();

        //
        // GET: /Admin/Coordinator/
        public ActionResult Index(int? id)
        {
            var viewModel = new CoordinatorIndexData
            {
                Coordinators = _db.Coordinators.Include(c => c.Projects).OrderBy(c => c.Name)
            };

            if (id == null)
            {
                return View(viewModel);
            }

            ViewBag.CoordinatorId = id.Value;
            viewModel.Projects = _db.Coordinators.Single(c => c.Id == id.Value).Projects;

            return View(viewModel);
        }

        //
        // GET: /Admin/Coordinator/Details/5
        public async Task<ActionResult> Details(int? id)
        {
            if(id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            var coordinator = await _db.Coordinators.FindAsync(id);
            if(coordinator == null)
            {
                return HttpNotFound();
            }
            return View(coordinator);
        }

        //
        // GET: /Admin/Coordinator/Create
        public ActionResult Create()
        {
            PopulateClubDropdownList();
            return View();
        }

        //
        // POST: /Admin/Coordinator/Create
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Create([Bind(Include = "ClubId,Name,PhoneNumber,CoordinatorEmailAddress")] Coordinator coordinator)
        {
            try
            {
                coordinator.Modified = DateTime.UtcNow;

                coordinator.IpAddress = GetUserIp();

                if(ModelState.IsValid)
                {
                    coordinator.PhoneNumber = "";
                    coordinator.Projects = new List<Project>();

                    _db.Coordinators.Add(coordinator);
                    await _db.SaveChangesAsync();
                    return RedirectToAction("Index");
                }
            }
            catch(RetryLimitExceededException /* dex */)
            {
                //Log the error (uncomment dex variable name and add a line here to write a log.
                ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
            }
            PopulateClubDropdownList(coordinator.ClubId);
            return View(coordinator);
        }

        //
        // GET: /Admin/Coordinator/Edit/5
        public async Task<ActionResult> Edit(int? id)
        {
            if(id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            var coordinator = await _db.Coordinators.FindAsync(id);
            if(coordinator == null)
            {
                return HttpNotFound();
            }
            PopulateClubDropdownList(coordinator.ClubId);
            return View(coordinator);
        }

        //
        // POST: /Admin/Coordinator/Edit/5
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Edit([Bind(Include = "ID,ClubId,Name,PhoneNumber,CoordinatorEmailAddress,Modified,IpAddress")] Coordinator coordinator)
        {
            try
            {
                if(ModelState.IsValid)
                {
                    coordinator.Modified = DateTime.UtcNow;

                    coordinator.IpAddress = GetUserIp();

                    _db.Entry(coordinator).State = EntityState.Modified;
                    await _db.SaveChangesAsync();
                    return RedirectToAction("Index");
                }
            }
            catch(RetryLimitExceededException /* dex */)
            {
                //Log the error (uncomment dex variable name and add a line here to write a log.
                ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
            }
            PopulateClubDropdownList(coordinator.ClubId);
            return View(coordinator);
        }

        //
        // GET: /Admin/Coordinator/Delete/5
        public async Task<ActionResult> Delete(int? id, bool? saveChangesError = false)
        {
            if(id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            if(saveChangesError.GetValueOrDefault())
            {
                ViewBag.ErrorMessage = "Deleted failed. Try again, and if the problem persist see your system administrator.";
            }
            var coordinator = await _db.Coordinators.FindAsync(id);
            if(coordinator == null)
            {
                return HttpNotFound();
            }
            return View(coordinator);
        }

        //
        // POST: /Admin/Coordinator/Delete/5
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Delete(int id)
        {
            try
            {
                var coordinatorToDelete = new Coordinator { Id = id };
                _db.Entry(coordinatorToDelete).State = EntityState.Deleted;
                await _db.SaveChangesAsync();
            }
            catch(RetryLimitExceededException /* dex */)
            {
                //Log the error (uncomment dex variable name and add a line here to write a log.
                return RedirectToAction("Delete", new { id, saveChangesError = true });
            }

            return RedirectToAction("Index");
        }

        [ChildActionOnly]
        private string GetUserIp()
        {
            var ipList = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];

            return !string.IsNullOrEmpty(ipList)
                ? ipList.Split(',')[0]
                : Request.ServerVariables["REMOTE_ADDR"];
        }

        private void PopulateClubDropdownList(object selectedClub = null)
        {
            var clubsQuery = _db.Clubs.OrderBy(c => c.ClubTitle);
            ViewBag.ClubId = new SelectList(clubsQuery, "ID", "ClubTitle", selectedClub);
        }

        protected override void Dispose(bool disposing)
        {
            if(disposing)
            {
                _db.Dispose();
            }
            base.Dispose(disposing);
        }
	}
}